package vip.aster.workflow.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.validation.ProcessValidator;
import org.flowable.validation.ProcessValidatorFactory;
import org.flowable.validation.ValidationError;
import org.springframework.stereotype.Service;
import vip.aster.common.exception.BusinessException;
import vip.aster.common.utils.PageInfo;
import vip.aster.framework.security.entity.SecurityUser;
import vip.aster.framework.security.entity.UserDetail;
import vip.aster.system.entity.SysConfig;
import vip.aster.system.query.SysConfigQuery;
import vip.aster.workflow.bo.ProcessNode;
import vip.aster.workflow.constant.WorkFlowConstant;
import vip.aster.workflow.dto.DynamicDataDto;
import vip.aster.workflow.dto.FormItem;
import vip.aster.workflow.entity.WfForm;
import vip.aster.workflow.enums.CommonEnum;
import vip.aster.workflow.enums.FormEnum;
import vip.aster.workflow.enums.ProcessEnum;
import vip.aster.workflow.mapper.ProcessInstanceMapper;
import vip.aster.workflow.query.InstanceQuery;
import vip.aster.workflow.service.DataSourceService;
import vip.aster.workflow.service.ProcessService;
import vip.aster.workflow.service.WfFormService;
import vip.aster.workflow.task.TriggerTask;
import vip.aster.workflow.utils.DbUtil;
import vip.aster.workflow.vo.SubmitFormVO;
import vip.aster.workflow.vo.WfFormVO;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 流程 服务实现类
 * </P>
 *
 * @author Aster lipian1004@163.com
 * @since 2024-04-15 14:28:44
 */
@Slf4j
@Service
@AllArgsConstructor
public class ProcessServiceImpl implements ProcessService {

    /**
     * 数据源service
     */
    private DataSourceService dataSourceService;

    /**
     * 流程表单service
     */
    private WfFormService wfFormService;

    /**
     * 运行时流程service
     */
    private RuntimeService runtimeService;

    /**
     * 工作流资源service
     */
    private RepositoryService repositoryService;

    /**
     * 流程实例mapper
     */
    private ProcessInstanceMapper processInstanceMapper;

    /**
     * 启动流程
     *
     * @param code 流程编码
     * @return 流程实例ID
     */
    public String start(String code) {
        // 获取当前人
        UserDetail user = SecurityUser.getUser();
        // 创建流程变量map
        Map<String, Object> processVar = new HashMap<>();
        // 放入当前人
        processVar.put(WorkFlowConstant.START_USER, user.getId());
        // 启动流程
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(code, processVar);
        return processInstance.getProcessInstanceId();
    }

    /**
     * 部署流程
     *
     * @param entity 流程表单
     */
    @Override
    public void deployment(WfForm entity) {
        log.info("开始部署流程...");
        log.info("节点信息：{}", entity.getProcess());
        ProcessNode processNode = JSONObject.parseObject(entity.getProcess(), ProcessNode.class);
        BpmnModel bpmnModel = createBpmnModel(entity.getCode(), entity.getFormName(), processNode);
        ProcessValidatorFactory processValidatorFactory = new ProcessValidatorFactory();
        ProcessValidator defaultProcessValidator = processValidatorFactory.createDefaultProcessValidator();
        List<ValidationError> validate = defaultProcessValidator.validate(bpmnModel);
        if (CollectionUtils.isNotEmpty(validate)) {
            validate.forEach(validationError -> {
                log.error("流程校验, 节点：{}, 错误：{}", validationError.getActivityName(), validationError.getProblem());
            });
        }
        log.info("校验通过...");
        log.info("code：{}", entity.getCode());
        String xmlString = new String(new BpmnXMLConverter().convertToXML(bpmnModel));
        log.debug("bpmn-xml：{}", xmlString);
        Deployment deploy = repositoryService.createDeployment()
                .key(entity.getCode())
                .name(entity.getFormName())
                .addString(entity.getCode() + entity.getFormName() + ".bpmn", xmlString)
                .deploy();
        log.info("部署成功，部署ID：{}", deploy.getId());
        WfFormVO wfFormVO = wfFormService.getLastByFormCode(entity.getCode());
        String tableSql = DbUtil.createTable(entity);
        log.info("【创建表sql：{}】", tableSql);
//        dataSourceService.execute(tableSql);
        /*// 如果不为空，则更新表单
        if (wfFormVO != null) {
            // 处理列信息
            wfFormService.handleField(entity, wfFormVO);
        } else {
            String tableSql = DbUtil.createTable(entity);
            log.info("【创建表sql：{}】", tableSql);
            dataSourceService.execute(tableSql);
        }*/
    }

    /**
     * 提交表单并启动流程
     *
     * @param submitFormVO 表单数据
     */
    @Override
    public void submit(SubmitFormVO submitFormVO) {
        // 通过主键查询表单
        WfForm wfForm = wfFormService.getById(submitFormVO.getFormId());
        Map<String, Object> formData = submitFormVO.getFormData();
        Map<String, Object> saveDataMap = new HashMap<>(formData);
        if (!StringUtils.isBlank(wfForm.getFormItems())) {
            JSONArray fieldJsonArray = JSONArray.parseArray(wfForm.getFormItems());
            // 获取所有的表单属性
            List<String> fieldIdList = getFieldIds(fieldJsonArray);
            for (String key : formData.keySet()) {
                if (!fieldIdList.contains(key)) {
                    saveDataMap.remove(key);
                }
            }
        }
        // 设置默认值
        setDefaultValue(saveDataMap);
        if (submitFormVO.getFormStatus().equals(ProcessEnum.FormStatusEnum.START.getValue())) {
            // 通过表单编码启动流程返回流程实例ID
            String processInstanceId = this.start(wfForm.getCode());
            saveDataMap.put(WorkFlowConstant.PROCESS_INSTANCE_ID, processInstanceId);
            saveDataMap.put(WorkFlowConstant.FORM_STATUS, ProcessEnum.FormStatusEnum.START.getValue());
        }
        // 表单数据
        DynamicDataDto dynamicDataDto = new DynamicDataDto();
        dynamicDataDto.setFormData(saveDataMap);
        dynamicDataDto.setTableName(wfForm.getCode());
        dataSourceService.save(dynamicDataDto);
    }

    /**
     * 查询待办数据
     *
     * @param query 查询条件
     * @return 待办数据
     */
    @Override
    public PageInfo<Map<String, Object>> selectTask(Map<String, Object> query) {
        int pageNum = query.containsKey("pageNum") ? MapUtil.getInt(query, "pageNum") : 1;
        int pageSize = query.containsKey("pageSize") ? MapUtil.getInt(query, "pageSize") : 10;
        Page<Map<String, Object>> page = new Page<>(pageNum, pageSize);
        DynamicDataDto pageQuery = new DynamicDataDto();
        pageQuery.setTableName(MapUtil.getStr(query, "code"));
        IPage<Map<String, Object>> pageList = processInstanceMapper.selectTask(page, pageQuery);
        return new PageInfo<>(pageList.getRecords(), pageList.getTotal());
    }

    /**
     * 获取所有已审批通过的流程实例
     *
     * @param code 表单CODE
     * @return list
     */
    @Override
    public List<JSONObject> selectCompletedInstances(String code) {
        List<String> columns = processInstanceMapper.selectColumns(code);
        if (CollUtil.isEmpty(columns)) {
            return ListUtil.empty();
        }
        String columnsStr = CollUtil.join(columns, ",");
        String status = ProcessEnum.FormStatusEnum.END.getValue();
        return processInstanceMapper.selectCompletedInstances(code, columnsStr, status);
    }

    @Override
    public boolean isTableExists(String tableName) {
        int count = processInstanceMapper.isTableExists(tableName);
        return count > 0;
    }

    /**
     * 流程实例分页
     *
     * @param code          表单编码
     * @param instanceQuery 查询条件
     * @return 分页
     */
    @Override
    public PageInfo<JSONObject> selectInstancePageByCode(String code, InstanceQuery instanceQuery) {
        if (StrUtil.isBlank(code)) {
            throw new BusinessException("表单编码不能为空！");
        }
        // 检查表是否存在
        if (!this.isTableExists(code)) {
            return new PageInfo<>(ListUtil.empty(), 0L);
        }
        // 拼接查询列
        String selectColumns = "";
        List<String> columns = instanceQuery.getColumns();
        if (CollUtil.isEmpty(columns)) {
            selectColumns = " * ";
        } else {
            selectColumns = StrUtil.join(",", columns);
            if (!selectColumns.contains(WorkFlowConstant.ID)) {
                selectColumns += ", " + WorkFlowConstant.ID;
            }
            if (!selectColumns.contains(WorkFlowConstant.CREATE_TIME)) {
                selectColumns += ", " + WorkFlowConstant.CREATE_TIME;
            }
            if (!selectColumns.contains(WorkFlowConstant.CREATE_BY)) {
                selectColumns += ", " + WorkFlowConstant.CREATE_BY;
            }
            if (!selectColumns.contains(WorkFlowConstant.FORM_STATUS)) {
                selectColumns += ", " + WorkFlowConstant.FORM_STATUS;
            }
        }
        // 分页参数
        Page<JSONObject> page = new Page<>(instanceQuery.getPageNum(), instanceQuery.getPageSize());
        // 查询条件
        QueryWrapper<JSONObject> queryWrapper = this.getInstanceWrapper(instanceQuery.getCustomParams(), instanceQuery.getCustomItems());
        // 分页
        IPage<JSONObject> pageList = processInstanceMapper.selectPage(page, queryWrapper, code, selectColumns);
        return new PageInfo<>(pageList.getRecords(), pageList.getTotal());
    }

    /**
     * 生成自定义查询条件
     *
     * @param customParams 自定义查询参数
     * @param customItems  自定义查询配置
     * @return QueryWrapper
     */
    private QueryWrapper<JSONObject> getInstanceWrapper(JSONObject customParams, JSONArray customItems) {
        // 查询条件
        QueryWrapper<JSONObject> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("create_time");
        // 若为空则直接返回
        if (customParams.isEmpty() || CollUtil.isEmpty(customItems)) {
            return queryWrapper;
        }
        for (Map.Entry<String, Object> param : customParams.entrySet()) {
            String fieldId = param.getKey();
            Object value = param.getValue();
            String valueType = this.getFieldValueType(fieldId, customItems);

            if (StrUtil.isBlank(fieldId) || value == null || StrUtil.isBlank(value.toString())) {
                continue;
            }

            if (FormEnum.ValueTypeEnum.STRING.getName().equals(valueType)) {
                // 字符串 like
                queryWrapper.like(fieldId, value.toString());
            } else if (FormEnum.ValueTypeEnum.NUMBER.getName().equals(valueType)) {
                // 数值 大于等于
                queryWrapper.ge(fieldId, Double.valueOf(value.toString()));
            } else if (FormEnum.ValueTypeEnum.OBJECT.getName().equals(valueType)) {
                // 对象 等于
                queryWrapper.eq(fieldId, value);
            } else if (FormEnum.ValueTypeEnum.DATE.getName().equals(valueType)) {
                // 日期 大于等于
                queryWrapper.ge(fieldId, DateUtil.parse(value.toString()));
            } else if (FormEnum.ValueTypeEnum.DATE_RANGE.getName().equals(valueType)) {
                // 日期范围
                JSONArray dateRange = JSONArray.parseArray(JSON.toJSONString(value));
                if (dateRange.size() == 2) {
                    queryWrapper.ge(fieldId, DateUtil.parse(dateRange.getString(0)));
                    queryWrapper.le(fieldId, DateUtil.parse(dateRange.getString(1)));
                }
            } else if (FormEnum.ValueTypeEnum.ARRAY.getName().equals(valueType)
                    || FormEnum.ValueTypeEnum.USER.getName().equals(valueType)
                    || FormEnum.ValueTypeEnum.DEPT.getName().equals(valueType)) {
                // 数组、用户、部门
                JSONArray array = JSONArray.parseArray(JSON.toJSONString(value));
                if (array.isEmpty()) {
                    continue;
                }
                if (array.size() == 1) {
                    queryWrapper.like(fieldId, array.get(0));
                } else {
                    queryWrapper.eq(fieldId, array);
                }

            }
        }
        return queryWrapper;
    }

    private String getFieldValueType(String fieldId, JSONArray customItems) {
        List<FormItem> items = JSONArray.parseArray(JSONArray.toJSONString(customItems), FormItem.class);
        for (FormItem item : items) {
            if (item.getId().equals(fieldId)) {
                return item.getValueType();
            }
        }
        return FormEnum.ValueTypeEnum.STRING.getName();
    }

    /**
     * 获取表单项ID集合
     *
     * @param itemJsonArray 表单项JSON集合
     * @return 表单项ID集合
     */
    private List<String> getFieldIds(JSONArray itemJsonArray) {
        List<FormItem> formFieldList = getFormFields(itemJsonArray, new ArrayList<FormItem>());
        if (CollectionUtils.isEmpty(formFieldList)) {
            return new ArrayList<String>();
        }
        return formFieldList.stream().map(FormItem::getId).collect(Collectors.toList());
    }

    /**
     * 获取表单项
     *
     * @param itemJsonArray 表单项JSON集合
     * @param fieldList     表单项集合
     * @return 表单项集合
     */
    private List<FormItem> getFormFields(JSONArray itemJsonArray, List<FormItem> fieldList) {
        if (itemJsonArray != null && !itemJsonArray.isEmpty()) {
            for (int i = 0; i < itemJsonArray.size(); i++) {
                JSONObject itemJson = itemJsonArray.getJSONObject(i);
                String name = itemJson.getString("name");
                // 如果是GridLayout
                if (name.equals(ProcessEnum.FormComponentEnum.GridLayout.toString())) {
                    JSONObject propsJSON = itemJson.getJSONObject("props");
                    JSONArray items = propsJSON.getJSONArray("items");
                    if (items != null && !items.isEmpty()) {
                        for (int j = 0; j < items.size(); j++) {
                            // 递归获取列信息
                            getFormFields(items.getJSONArray(j), fieldList);
                        }
                    }
                } else if (name.equals(ProcessEnum.FormComponentEnum.GridTitle.toString())) {
                    JSONObject propsJSON = itemJson.getJSONObject("props");
                    JSONArray items = propsJSON.getJSONArray("items");
                    // 递归获取列信息
                    getFormFields(items, fieldList);
                }
                fieldList.add(itemJson.toJavaObject(FormItem.class));
            }
        }
        return fieldList;
    }

    /**
     * 设置默认值
     *
     * @param formData 表单数据
     */
    private void setDefaultValue(Map<String, Object> formData) {
        UserDetail user = SecurityUser.getUser();
        if (user != null) {
            formData.put(WorkFlowConstant.CREATE_BY, user.getId());
            formData.put(WorkFlowConstant.CREATE_TIME, LocalDateTime.now());
        }
        formData.put(WorkFlowConstant.ID, IdUtil.fastSimpleUUID());
        formData.put(WorkFlowConstant.FORM_STATUS, ProcessEnum.FormStatusEnum.DRAFT.getValue());
        formData.put(WorkFlowConstant.IS_DELETED, CommonEnum.DeleteEnum.UN_DELETE.getValue());
    }

    /**
     * 创建BpmnModel对象
     *
     * @param id
     * @param name
     * @param processNode
     * @return
     */
    @Override
    public BpmnModel createBpmnModel(String id, String name, ProcessNode processNode) {
        Map<String, FlowElement> elementMap = new LinkedHashMap<>();

        //构建流程
        Process process = new Process();
        process.setId(id);
        process.setName(name);

        // 创建开始节点
        StartEvent startEvent = createStartNode(id);
        process.addFlowElement(startEvent);

        if (processNode != null) {
            convertBpmnModel(id, processNode, elementMap);
        }

        // 创建结束节点
        EndEvent endEvent = createEndNode();
        process.addFlowElement(endEvent);

        Iterator<Map.Entry<String, FlowElement>> iterator = elementMap.entrySet().iterator();
        int i = 0;
        String firstId = "";
        String lastId = "";
        while (iterator.hasNext()) {
            Map.Entry<String, FlowElement> nodeElement = iterator.next();
            if (i == 0) {
                firstId = nodeElement.getKey();
            } else {
                lastId = nodeElement.getKey();
            }
            i++;
        }
        if (StringUtils.isBlank(lastId)) {
            lastId = firstId;
        }

        // 创建开始节点连线
        createLine(startEvent.getId(), firstId, elementMap);

        // 创建结束节点连线
        createLine(lastId, endEvent.getId(), elementMap);

        elementMap.values().forEach(process::addFlowElement);

        //构建Bpmn模型
        BpmnModel bpmnModel = new BpmnModel();
        bpmnModel.addProcess(process);

        // todo 自动生成布局节点位置

        return bpmnModel;
    }

    /**
     * 转换流程节点
     *
     * @param id
     * @param node
     * @param elementMap
     */
    public void convertBpmnModel(String id, ProcessNode node, Map<String, FlowElement> elementMap) {
        if (StringUtils.isBlank(node.getId())) {
            node.setId("node_" + IdUtil.simpleUUID());
        }
        if (!StringUtils.isBlank(node.getId())) {
            FlowElement element = null;
            if (node.getType().equals(ProcessEnum.WebNodeTypeEnum.ROOT.getValue())) {
                element = createStartNode(id, node);
            } else if (node.getType().equals(ProcessEnum.WebNodeTypeEnum.APPROVAL.getValue())) {
                element = createApprovalNode(id, node);
            } else if (node.getType().equals(ProcessEnum.WebNodeTypeEnum.SEND.getValue())) {
                element = createSendTask(node);
            } else if (node.getType().equals(ProcessEnum.WebNodeTypeEnum.CONDITIONS.getValue())) {
                element = createConditionsNode(node);
            }
            /*switch (node.getType()) {
                // 发起人
                case ProcessEnum.WebNodeTypeEnum.ROOT.getNode() -> element = createStartNode(node);
                // 办理
                case TASK -> element = createApprovalNode(node);
                // 审批
                case APPROVAL -> element = createApprovalNode(node);
                // 抄送
                case SEND -> element = createSendTask(node);
                // 延迟
                case DELAY -> element = createDelayNode(node);
                // 包容网关
                case INCLUSIVES -> element = createInclusiveNode(node);
                // 条件
                case CONDITIONS -> element = createConditionsNode(node);
                // 并行
                case CONCURRENTS -> element = createConcurrentNode(node);
                // 触发器
                case TRIGGER -> element = createTriggerTask(node);
                // 空的
                case EMPTY -> element = createEmptyNode(node);
            }*/
            if (element != null) {
                elementMap.put(node.getId(), element);
            }
            // todo 连线
//            createLine();
            List<ProcessNode> childNode = node.getChildNode();
            if (!CollectionUtils.isEmpty(childNode)) {
                for (ProcessNode processNode : childNode) {
                    String nodeId = "node_" + IdUtil.simpleUUID();
                    processNode.setId(nodeId);
                    createLine(node.getId(), nodeId, elementMap);
                    convertBpmnModel(id, processNode, elementMap);
                }
            }
        }
    }

    /**
     * 创建连线
     *
     * @param startId
     * @param endId
     * @param elementMap
     * @return
     */
    private SequenceFlow createLine(String startId, String endId, Map<String, FlowElement> elementMap) {
        SequenceFlow flow = new SequenceFlow();
        flow.setId(startId + "-" + endId);
        flow.setSourceRef(startId);
        flow.setTargetRef(endId);
        elementMap.put(flow.getId(), flow);
        return flow;
    }


    /**
     * 发起人节点
     *
     * @param formKey
     * @param node
     * @return
     */
    private UserTask createStartNode(String formKey, ProcessNode node) {
        UserTask userTask = new UserTask();
        userTask.setId(node.getId());
        userTask.setName(node.getNodeName());
        userTask.setFormKey(formKey);
        userTask.setAssignee(WorkFlowConstant.START_USER_ASSIGNEE);
        return userTask;
    }


    /**
     * 审批任务
     *
     * @param formKey 表单code
     * @param node    节点信息
     * @return
     */
    private UserTask createApprovalNode(String formKey, ProcessNode node) {
        UserTask userTask = new UserTask();
        userTask.setId(node.getId());
        userTask.setName(node.getNodeName());
        userTask.setFormKey(formKey);
        if (node.getSettype().equals(ProcessEnum.NodeSetTypeEnum.MINE.getType())) {
            // 发起人自己
            userTask.setAssignee(WorkFlowConstant.START_USER_ASSIGNEE);
        }
        /*ApprovalProps props = node.getProps();
        //全部按多人审批处理
        userTask.setTaskListeners(taskListeners);
        if(ApprovalTypeEnum.SELF.equals(props.getAssignedType())){
            //发起人自己审批
            userTask.setAssignee("${" + WflowGlobalVarDef.INITIATOR + "}");
        }else {
            userTask.setAssignee("${assignee}");
            userTask.setLoopCharacteristics(createAndOrMode(node.getId(), props));
        }
        userTask.setId(node.getId());
        //处理审批超时，添加定时器边界事件
        ApprovalProps.TimeLimit timeLimit = props.getTimeLimit();
        if (Objects.nonNull(timeLimit.getTimeout().getValue()) && timeLimit.getTimeout().getValue() > 0){
            BoundaryEvent boundaryEvent = new BoundaryEvent();
            boundaryEvent.setId(node.getId() + "-timeout");
            boundaryEvent.setName("审批超时");
            TimerEventDefinition timerEventDefinition = new TimerEventDefinition();
            String timeValue = getISO8601Time(timeLimit.getTimeout().getValue(), timeLimit.getTimeout().getUnit());
            timerEventDefinition.setTimeDuration(timeValue);
            if (ApprovalProps.TimeLimit.Handler.HandlerType.NOTIFY.equals(timeLimit.getHandler().getType())){
                //根据是否循环提醒来修改定时规则
                ApprovalProps.TimeLimit.Handler.Notify notify = timeLimit.getHandler().getNotify();
                if (!notify.isOnce()){
                    timerEventDefinition.setTimeDuration(null);
                    //默认最大10次，这里参考 https://en.wikipedia.org/wiki/ISO_8601#Repeating_intervals
                    timerEventDefinition.setTimeCycle("R10/" + timeValue);
                }
            }
            boundaryEvent.addEventDefinition(timerEventDefinition);
            boundaryEvent.setCancelActivity(false);
            boundaryEvent.setAttachedToRef(userTask);
            //创建边界事件的出口
            ServiceTask timeoutTask = new ServiceTask();
            timeoutTask.setId(node.getId() + "-timeoutTask");
            timeoutTask.setName(node.getNodeName() + "超时处理");
            timeoutTask.setImplementationType("class");
            timeoutTask.setImplementation(ApprovalTimeoutServiceTask.class.getName());
            addFlowEl(boundaryEvent);
            addFlowEl(timeoutTask);
            addFlowEl(createdConnectLine(boundaryEvent.getId(), timeoutTask.getId()));
        }*/
        return userTask;
    }


    /**
     * 抄送任务
     *
     * @param node
     * @return
     */
    private ServiceTask createSendTask(ProcessNode node) {
        ServiceTask ccTask = new ServiceTask();
        ccTask.setId(node.getId());
        ccTask.setName(node.getNodeName());
        ccTask.setImplementationType("class");
//        ccTask.setImplementation(CcServiceTask.class.getName());
        //ccTask.addAttribute();
        return ccTask;
    }


    private IntermediateCatchEvent createDelayNode(ProcessNode node) {
        IntermediateCatchEvent catchEvent = new IntermediateCatchEvent();
        TimerEventDefinition timerDefinition = new TimerEventDefinition();
        /*DelayProps props = node.getProps();
        if (props.getType().equals(DelayProps.Type.FIXED)) {
            timerDefinition.setTimeDuration(getISO8601Time(props.getTime(), props.getUnit()));
        } else {
            //动态计算时长
            timerDefinition.setTimeDate("${uelTools.getDelayDuration(execution)}");
        }*/
        catchEvent.setId(node.getId());
        catchEvent.setName(node.getNodeName());
        //插入定时器捕获中间事件
        catchEvent.addEventDefinition(timerDefinition);
        return catchEvent;
    }


    /**
     * 包容网关
     *
     * @param node
     * @return
     */
    private InclusiveGateway createInclusiveNode(ProcessNode node) {
        InclusiveGateway inclusiveGateway = new InclusiveGateway();
        inclusiveGateway.setExclusive(true);
        inclusiveGateway.setId(node.getId());
        inclusiveGateway.setName(ProcessEnum.NodeTypeEnum.EMPTY.equals(node.getType()) ? "包容分支聚合" : "包容分支");
        return inclusiveGateway;
    }

    /**
     * 排他网关
     *
     * @param node
     * @return
     */
    private ExclusiveGateway createConditionsNode(ProcessNode node) {
        ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
        exclusiveGateway.setExclusive(true);
        exclusiveGateway.setId(node.getId());
        exclusiveGateway.setName(ProcessEnum.NodeTypeEnum.EMPTY.equals(node.getType()) ? "条件分支聚合" : "条件分支");
        return exclusiveGateway;
    }

    /**
     * 并行网关
     *
     * @param node
     * @return
     */
    private ParallelGateway createConcurrentNode(ProcessNode node) {
        ParallelGateway parallelGateway = new ParallelGateway();
        parallelGateway.setId(node.getId());
        parallelGateway.setName(ProcessEnum.NodeTypeEnum.EMPTY.equals(node.getType()) ? "并行分支聚合" : "并行分支");
        return parallelGateway;
    }

    /**
     * 触发器任务
     *
     * @param node
     * @return
     */
    private FlowElement createTriggerTask(ProcessNode node) {
        ServiceTask ccTask = new ServiceTask();
        ccTask.setId(node.getId());
        ccTask.setName(node.getNodeName());
        ccTask.setImplementationType(WorkFlowConstant.IMPLEMENTATION_TYPE);
        ccTask.setImplementation(TriggerTask.class.getName());
        return ccTask;
    }

    /**
     * 创建空节点
     *
     * @param node
     * @return
     */
    private FlowElement createEmptyNode(ProcessNode node) {
        FlowElement element = null;
        if (ProcessEnum.NodeTypeEnum.CONCURRENTS.equals(node.getParentType())) {
            //并行网关成对存在，因此再添加一个聚合节点
            element = createConcurrentNode(node);
        } else if (ProcessEnum.NodeTypeEnum.CONDITIONS.equals(node.getParentType())) {
            //构造条件网关合流点
            element = createConditionsNode(node);
        } else if (ProcessEnum.NodeTypeEnum.INCLUSIVES.equals(node.getParentType())) {
            element = createInclusiveNode(node);
        }
        return element;
    }


    private StartEvent createStartNode(String formKey) {
        StartEvent startEvent = new StartEvent();
        startEvent.setId(ProcessEnum.NodeEnum.START.getName());
        startEvent.setName(ProcessEnum.NodeEnum.START.getValue());
        startEvent.setFormKey(formKey);
        return startEvent;
    }


    private EndEvent createEndNode() {
        EndEvent endEvent = new EndEvent();
        endEvent.setId(ProcessEnum.NodeEnum.END.getName());
        endEvent.setName(ProcessEnum.NodeEnum.END.getValue());
        return endEvent;
    }

}
